#include <iostream>
#include <string>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mutex>

#include "Mutex.hpp"
using namespace std;
using namespace MutexModue;

int ticket = 1000;
//定义全局的锁
// pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;

//C++库里面的锁
// mutex cpp_lock;

class ThreadData
{
public:
    ThreadData(const string& n,Mutex& lock)
        :name(n),
        lockp(&lock)
        {}
    ~ThreadData()
    {

    }
    string name;
    Mutex* lockp;
};

//锁的范围应该足够小，保护临界区代码，尽可能少的包含非临界区
void* routine(void* args)
{
    
    ThreadData* td = static_cast<ThreadData*>(args);

    while(1)
    {
        //RAII风格的互斥锁的实现
        //在每进行一次循环就重新创建锁，自动销毁之前的锁
        LockGuard lock(*td->lockp);
        if(ticket > 0)
        {
            usleep(1000);
            printf("%s sells ticket %d\n",td->name.c_str(), ticket);
            ticket--;

        }
        else
        {
            break;
        }
        usleep(100);
    }
    return nullptr;
}

// void* routine(void* args)
// {
    
//     ThreadData* td = static_cast<ThreadData*>(args);

//     while(1)
//     {
//         //加锁 td->lockp的类型是pthread_mutex_t*
//         // pthread_mutex_lock(td->lockp);
//         // pthread_mutex_lock(&glock);
//         // td->lockp->Lock();

//         cpp_lock.lock();
//         if(ticket > 0)
//         {
//             usleep(1000);
//             printf("%s sells ticket %d\n",td->name.c_str(), ticket);
//             ticket--;
//             // pthread_mutex_unlock(td->lockp;
//             // pthread_mutex_unlock(&glock);
//             // td->lockp->Unlock();

//             cpp_lock.unlock();
//         }
//         else
//         {
//             // pthread_mutex_unlock(td->lockp);
//             // pthread_mutex_unlock(&glock);
//             // td->lockp->Unlock();

//             cpp_lock.unlock();
//             break;
//         }
//     }
//     return nullptr;
// }

int main()
{
    //局部定义的锁
    // pthread_mutex_t plock;
    // pthread_mutex_init(&plock, nullptr);

    pthread_t t1,t2,t3,t4;
    
    Mutex lock;
    ThreadData* td1 = new ThreadData("thread-1", lock);
    pthread_create(&t1, nullptr, routine, td1);

    ThreadData* td2 = new ThreadData("thread-2", lock);
    pthread_create(&t2, nullptr, routine, td2);

    ThreadData* td3 = new ThreadData("thread-3", lock);
    pthread_create(&t3, nullptr, routine, td3);

    ThreadData* td4 = new ThreadData("thread-4", lock);
    pthread_create(&t4, nullptr, routine, td4);

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);

    //销毁锁
    // pthread_mutex_destroy(&lock);
    return 0;
}
